package com.famiover.generator.plugins;

import com.famiover.generator.generator.MybatisCodeGenerator;
import com.famiover.generator.utils.Utils;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.*;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;


public class ModelJavaPlugin extends PluginAdapter {

    public static String id;

    @Override
    public boolean validate(List<String> warnings) {
        return true;
    }

    @Override
    public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        boolean extend = Utils.isExtend(context);
        id = Utils.getPropertyDefault(context, "id", "id");
        modelExtendBaseModel(extend, topLevelClass, introspectedTable);
        return true;
    }


    private String getIdx(IntrospectedTable introspectedTable) {
        List<String> cols = introspectedTable.getAllColumns().stream().map(IntrospectedColumn::getActualColumnName).collect(Collectors.toList());
        for (String col : cols) {
            if (col.equals(id)) {
                return col;
            }
        }
        return null;
    }


    private void modelExtendBaseModel(boolean extend, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        if (!extend) {
            return;
        }

        Utils.modelAddAnnotation(topLevelClass, "lombok.Getter", "@Getter");
        Utils.modelAddAnnotation(topLevelClass, "lombok.Setter", "@Setter");
        Utils.modelAddAnnotation(topLevelClass, "lombok.ToString", "@ToString");


        String baseModelPath = Utils.getProperty(context, "baseModelPath");
        topLevelClass.addImportedType(new FullyQualifiedJavaType(baseModelPath));
        FullyQualifiedJavaType fullyQualifiedJavaType = MybatisCodeGenerator.getPrimaryKeyFullyQualifiedJavaType(introspectedTable);
        String shortName = MybatisCodeGenerator.getPrimaryKeyShortName(introspectedTable);
        Preconditions.checkNotNull(fullyQualifiedJavaType, "不能为空!");
        topLevelClass.addImportedType(fullyQualifiedJavaType);
        Preconditions.checkArgument(Objects.nonNull(shortName) && shortName.length() > 0, "不能为空!");
        topLevelClass.setSuperClass(String.format("%s<%s>", baseModelPath, shortName));
        topLevelClass.addJavaDocLine("/**");
        topLevelClass.addJavaDocLine("* 表:" + introspectedTable.getTableConfiguration().getTableName());
        topLevelClass.addJavaDocLine("*");
        topLevelClass.addJavaDocLine("* @author dongrongjun");
        topLevelClass.addJavaDocLine("*/");

        String idx = getIdx(introspectedTable);
        if (Utils.isEmpty(idx)) {
            addIdMethod(topLevelClass, introspectedTable);
        }

    }

    public void addIdMethod(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        Method method1 = new Method();
        method1.addAnnotation("@Override");
        FullyQualifiedJavaType fullyQualifiedJavaType = introspectedTable.getPrimaryKeyColumns().get(0).getFullyQualifiedJavaType();
        String actualColumnName = introspectedTable.getPrimaryKeyColumns().get(0).getActualColumnName();
        String idField = Utils.toLowerCamel(actualColumnName);
        method1.setVisibility(JavaVisibility.PUBLIC);
        method1.setReturnType(fullyQualifiedJavaType);
        String s = Utils.toUpperCamel(id);
        method1.setName("get" + s);
        List<String> stringList1 = Lists.newArrayList();
        stringList1.add("this." + id + " = " + idField + ";");
        stringList1.add("return " + idField + ";");
        method1.addBodyLines(stringList1);
        topLevelClass.addMethod(method1);

        List<String> stringList2 = Lists.newArrayList();
        Method method2 = new Method();
        method2.addAnnotation("@Override");
        method2.setVisibility(JavaVisibility.PUBLIC);
        method2.setName("set" + s);
        method2.addParameter(new Parameter(fullyQualifiedJavaType, id));
        stringList2.add("this." + id + " = " + id + ";");
        stringList2.add("this." + idField + " = " + id + ";");
        method2.addBodyLines(stringList2);
        topLevelClass.addMethod(method2);

        Field field = new Field();
        field.setName(id);
        field.setType(fullyQualifiedJavaType);
        field.setVisibility(JavaVisibility.PRIVATE);
        topLevelClass.addField(field);

    }


    @Override
    public boolean modelSetterMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) {
        return false;
    }

    @Override
    public boolean modelGetterMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) {
        return false;
    }
}
